using System;
using System.Collections;
using System.Resources;
using System.Runtime.InteropServices;

namespace Microsoft.Win32 
{
	/// <summary>
	/// An exception encpsulating a Native Win32 error.
	/// </summary>
	public class Win32Exception : Exception
	{
    #region Private Property Declarations
    /// <summary>Private Property Declaration. <see cref="NativeError"/></summary>
    private NativeError p_NativeError;
    #endregion
    #region Public Property Delcarations
    /// <summary>
    /// The error thrown by the Win32 Shell.
    /// </summary>
    public NativeError NativeError
    {
      get{return p_NativeError;}
      set{p_NativeError = value;}
    }
    #endregion
    #region Constructors
		public Win32Exception() : base(Check(false).ToString())
		{
      p_NativeError = Check(false);
		}

    public Win32Exception(string message) : base(message)
    {
      p_NativeError = Check(false);
    }

    public Win32Exception(string message, Exception innerException) : base(message,innerException)
    {
      p_NativeError = Check(false);
    }

    public Win32Exception(NativeError nativeErr) : base(GetErrorMessage(nativeErr))
    {
      p_NativeError = nativeErr;
    }

    public Win32Exception(string message, NativeError nativeErr) : base(message)
    {
      p_NativeError = nativeErr;
    }

    public Win32Exception(string message, NativeError nativeErr, Exception innerException) : base(message,innerException)
    {
      p_NativeError = nativeErr;
    }
    #endregion

    #region Public Static Declarations
    public static void Check()
    {
      Check(true);
    }

    public static NativeError Check(bool throwException)
    {
      NativeError native = (NativeError) Marshal.GetLastWin32Error();

      if(native!=NativeError.ERROR_SUCCESS&&throwException)
        throw new Win32Exception(GetErrorText(native),native);

      return native;
    }

    public static string GetErrorText(NativeError error)
    {
      IResourceReader rsxr = new ResXResourceReader("winerror.resx");

      try
      {
        foreach(DictionaryEntry d in rsxr)
          if((string)d.Key==error.ToString())
            return (string)d.Value;
      }
      finally
      {
        rsxr.Dispose();
      }
      
      return null;
    }

    #endregion
    #region Private Members
    private static string GetErrorMessage(NativeError error)
    {
      return "Windows threw error " + error.ToString() + "\n" + GetErrorText(error);
    }
    #endregion
	}
}
